package fr.univnantes.lina.uima.connectors.wst;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Vector;
import org.apache.uima.UimaContext;
import org.apache.uima.analysis_component.JCasAnnotator_ImplBase;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.cas.CAS;
import org.apache.uima.cas.CASException;
import org.apache.uima.cas.FSIterator;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.text.AnnotationIndex;
import org.apache.uima.examples.SourceDocumentInformation;
import org.apache.uima.jcas.JCas;
import org.apache.uima.jcas.tcas.Annotation;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.resource.ResourceProcessException;
import org.apache.uima.util.CasToInlineXml;

import fr.univnantes.lina.java.util.JavaUtilities;
import fr.univnantes.lina.uima.common.AnnotationCollectionUtils;
import fr.univnantes.lina.uima.common.AnnotationUtils;
import fr.univnantes.lina.uima.common.CommonAE;
import fr.univnantes.lina.uima.common.DocumentAnnotationUtils;
import fr.univnantes.lina.uima.common.FeatureUtils;
import fr.univnantes.lina.uima.common.JCasSofaViewUtils;
import fr.univnantes.lina.uima.common.UIMAUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;



/**
 * Create a new view turning into WST format sentence and the word annotations of a given view
 * <p>
 * This AE takes two parameters:
 * <ul>
 * <li><code>InputView</code> - view where are defined the sentence and the word annotations. Optional, by default 
 * <code>_InitialView</code></li>
 * <li><code>OutputView</code> - view to create with words and sentences in the WST format. Mandatory.</li>
 * <li><code>SentenceType</code> - type name of the Sentence annotations to turn into sentences separated by a newline character. Optional, by default <code>org.apache.uima.SentenceAnnotation</code></li>
 * <li><code>WordType</code> - type name of the Word annotations to turn into word separated by a whitespace character. Optional, by default <code>org.apache.uima.TokenAnnotation</code></li>
 * </ul>
 * 
 * 
 */
public class CAS2WSTAE extends CommonAE {

	/*
	 * PARAMETERS NAMES
	 */
	/**
	 * Parameter name of the sentence type
	 */
	public static final String PARAM_SENTENCE_TYPE = "SentenceType";

	/**
	 * Parameter name of the word type 
	 */
	public static final String PARAM_WORD_TYPE = "WordType";

	/**
	 * Parameter name of the feature of the word type 
	 */
	public static final String PARAM_FEATURE_NAME = "FeatureName";

	/*
	 * PARAMETERS DEFAULT VALUES
	 */
	/**
	 * Default value of the word type
	 */
	public static String DEFAULT_WORD_TYPE = "org.apache.uima.TokenAnnotation";
	
	/**
	 * Default value of the feature of the word type
	 */
	public static String DEFAULT_FEATURE_NAME = "coveredText";
	
	
	/**
	 * Default value of the sentence type
	 */
	public static String DEFAULT_SENTENCE_TYPE = "org.apache.uima.SentenceAnnotation";

	/**
	 * Default sentence end character value
	 */
	public static String DEFAULT_SENTENCE_END_CHARACTER_VALUE =	"\n" ;
	
	/*
	 * LOCAL VARIABLES
	 */
		
	private String sentenceTypeName;
	private String wordTypeName;
	private String featureName;
	
	/*
	 * ACCESSORS
	 */


	/*
	 * METHODS 
	 */

	/**
	 * Get the parameter values, setting the variables and checking the values 
	 */
	public void initialize(UimaContext aContext) throws ResourceInitializationException {

		// SUPER PARAMETER SETTINGS
		super.initialize(aContext);

		// CURRENT AE PARAMETER SETTINGS
		sentenceTypeName = ((String) aContext.getConfigParameterValue(PARAM_SENTENCE_TYPE));
		if (sentenceTypeName == null) sentenceTypeName = DEFAULT_SENTENCE_TYPE;
		
		wordTypeName = ((String) aContext.getConfigParameterValue(PARAM_WORD_TYPE));
		if (wordTypeName == null) wordTypeName = DEFAULT_WORD_TYPE;
		
		featureName = ((String) aContext.getConfigParameterValue(PARAM_FEATURE_NAME));
		if (featureName == null) featureName = DEFAULT_FEATURE_NAME;
	
		//try {
		//} catch (Exception e) {
		//	String errmsg = "!";
		//	throw new ResourceInitializationException(errmsg, new Object[] {});
		//}		
	}

	/**
	 * Based on the input view sentence and word annotations, <br>
	 * Create a text made of sentences separated by newline characters and words separated by whitespace characters.
	 * 
	 * @return the created text to be the dataString of the future created outputView
	 */
	@Override
	protected String processInputView(JCas inputViewJCas,
			FSIterator contextAnnotationsFSIter,
			HashMap<String, Integer> inputAnnotationStringHashMap,
			String inputFeatureString, JCas outputViewJCas,
			String outputAnnotationString, String ouputFeatureString)
	throws AnalysisEngineProcessException {
		
	

		// Set an hashmap with the word type name
		// Will be used for selecting the annotations subsumed by the sentence annotations
		HashMap<String, Integer> subSentenceAnnotationsHashMap = new HashMap<String, Integer>();
		subSentenceAnnotationsHashMap.put(wordTypeName, 1);
		
		//
		String outputText = "";
		
		// Get an iterator of sentences from the sentenceTypeName
		Type sentenceType = JCasSofaViewUtils.getJCasType(inputViewJCas, sentenceTypeName);
		AnnotationIndex<Annotation> sentenceAnnotationIndex = (AnnotationIndex<Annotation>) inputViewJCas
		.getAnnotationIndex(sentenceType);
		Iterator<Annotation> sentenceAnnotationIterator  = sentenceAnnotationIndex
		.iterator();

		//int counter = 0;
		//Date startDate = JavaUtilities.getNow();
		
		// For each sentence annotation 
		while (sentenceAnnotationIterator.hasNext()) {

			// a Sentence annotation
			Annotation aSentenceAnnotation = (Annotation) sentenceAnnotationIterator
			.next();
		
			// A constrained subiterator
			//FSIterator wordsAnnotationIterator = AnnotationCollectionUtils.subiterator(
			//		inputViewJCas, aSentenceAnnotation,
			//		subSentenceAnnotationsHashMap, false);
			// Much faster with a simple subiterator
			FSIterator wordsAnnotationIterator = AnnotationCollectionUtils.subiterator(
					inputViewJCas, aSentenceAnnotation);
			
			// write a new line of word separated by whitespace character 
			String aSentenceString = "";
			while (wordsAnnotationIterator.hasNext()) {
				Annotation aWordAnnotation = (Annotation) wordsAnnotationIterator
				.next();
				//String textWord = aWordAnnotation.getCoveredText();

				//System.out.println("Debug: aWordAnnotation.getClass().getName() "+aWordAnnotation.getClass().getName()+" wordTypeName"+ wordTypeName);
				if (aWordAnnotation.getClass().getName().equalsIgnoreCase(wordTypeName))  {
					//System.out.println("Debug: textWord>"+textWord+"<");
					String textWord = (String) FeatureUtils.getFeatureValue(aWordAnnotation, featureName);
					textWord = textWord.replaceAll("[\n\t]+", " ");
					textWord = textWord.replaceAll(" +", " ").trim();
					if (! textWord.equalsIgnoreCase("")) aSentenceString += " " + textWord;
				}
			}
			if (!aSentenceString.equalsIgnoreCase("")) {
				outputText += aSentenceString.substring(1) + DEFAULT_SENTENCE_END_CHARACTER_VALUE;
				//System.out.println("Debug: s>"+aSentenceString.substring(1)+"<");
			}
			//System.out.println("Debug: s" + counter+" >"+aSentenceString+"<");
			//counter++;
			
			//if (counter == 100) {
			//	Date endDate = JavaUtilities.getNow();
			//	System.err.println("Info: after 1000 lines : " + JavaUtilities.dateDiff(startDate, endDate));
		    //}
			
		}
		
		// return the outputText of the new outputview
		return outputText;
	}

}




